﻿package bdz.projects.lavender.doi.ui
{
	
	import bdz.common.events.*;
	import bdz.projects.lavender.doi.utils.DOIAudio;
	import flash.net.LocalConnection;
	
	import flash.display.MovieClip;
	import flash.events.MouseEvent;
	import flash.utils.*;
	
	import gs.*;
	import gs.easing.*;
	
	import org.papervision3d.cameras.*;
	import org.papervision3d.core.proto.GeometryObject3D;
	import org.papervision3d.events.InteractiveScene3DEvent;
	import org.papervision3d.materials.*;
	import org.papervision3d.objects.DisplayObject3D;
	import org.papervision3d.objects.primitives.Plane;
	import org.papervision3d.view.Viewport3D;
	
	/**
	 * ...
	 * @author ...
	 */
	public class DOIPlane extends DisplayObject3D 
	{
		protected var _frontContainer:DisplayObject3D;
		protected var _backContainer:DisplayObject3D;
		protected var _defobj:Object;
		protected var _renderer:String;
		protected var _ease:Function;
		protected var _speed:Number;
		protected var _viewport:Viewport3D;
		protected var _maxz:Number = 60;
		protected var _backPlane:MovieClip;
		protected var _backButtonLabel:String;
		protected var pmenu:PaperMenu;
		
		protected var _matref:Array;
		protected var _planeRef:Array;
		protected var _mcref:Array;
		protected var _frontmats:Array;
		
		protected var _backLabelPlane:Plane;
		protected var _backed:Number = 0;
		
		protected var _startz:Number = 1200;
		protected var _startfromback:Boolean = false;
		
		protected var _audio:DOIAudio;
		protected var _hasCustom:Boolean = false;
		public function DOIPlane(name:String, geometry:GeometryObject3D, startfromback:Boolean = false) {
			_speed = 1;
			_ease = Strong.easeInOut;
			super(name, geometry);
			_startfromback = startfromback;
			_frontmats = new Array();
			_matref = new Array();
			_mcref = new Array();
			_planeRef = new Array();
		}
		
		protected function renderPlane(delay:Number = 0):void {
			
			_audio = DOIAudio.getInstance();
			
			_backPlane = new PlaneBackFace();
			
			_frontContainer = new DisplayObject3D("_fronContainer");
			_backContainer = new DisplayObject3D("_backContainer");
			addChild(_backContainer);
			addChild(_frontContainer);
			
			
			_backContainer.rotationY = 180;
			if (_startfromback) {
				z = _startz;
				y = 100;
				scale = 0;
			}else{
				z = -_startz;
				y = -300;
			}
			if(_backed){
				rotationY = 0;
				_backContainer.z = 0;
				_frontContainer.z = -100;
				TweenMax.to(this, _speed + 1, { scale:1, delay:delay, z:100 * _backed, y:60 * _backed, rotationY:180, ease:_ease } );
				setTimeout(dispatchCreated, 200);
			}else{
				rotationY = 180;
				
				TweenMax.to(this, _speed + 1, { scale:1, delay:delay, z:0, y:0, rotationY:0, ease:_ease } );
				setTimeout(dispatchCreated, 200);
				_backContainer.visible = false;
				_backContainer.z = 100;
			}
			_audio.playFlip();
			
		}
		protected function dispatchCreated():void {
			
			dispatchEvent(new GenericEvent(GenericEvent.GENERATED));
		}
		protected function cleanUp(pobj:DisplayObject3D):void {
			
			pmenu.cleanUp();
			removeChild(pmenu);				
			for each(var mat:MovieMaterial in _matref) {
				try{
					mat.destroy();
				}catch (e:Error) {
					
				}
			}
			_matref = null;
			for each(var mc:MovieClip in _mcref) {
				
				mc = null;
				
			}
			_mcref = null;
			for each(var pl:Object in _planeRef) {
				try{
					pl.face.removeChild(pl.plane);
					pl = null;
				}catch (e:Error) {
				}
			}
			_planeRef = null;
			
			if(_backLabelPlane){
				_backContainer.removeChild(_backLabelPlane);
			}
			
			removeChild(_backContainer);
			removeChild(_frontContainer);
			pobj.removeChild(this);
			
			_backContainer = null;
			_frontContainer = null;
			pobj = null;
			
			_backLabelPlane = null;
			dispatchEvent(new GenericEvent("cleaned"));
			var lc:LocalConnection = new LocalConnection();
			try {
				lc.connect("bogus");
				lc.connect("bogus");
			}catch(e:Error){}
			
		}
		protected function showBackLabel():void {
			if (_backLabelPlane) {
				if(_backLabelPlane.z >0){
					TweenMax.to(_backLabelPlane, .9, { bezierThrough:[ { y:230, z:0 }, { y:185, z: -40 } ], rotationX:0, ease:Strong.easeInOut } );
				}
				_backLabelPlane.visible = true;
				
			}
		}
		protected function hideBackLabel():void {
			if (_backLabelPlane) {
				_backLabelPlane.y = 170;
				_backLabelPlane.x = _hasCustom ? -260 : -170;
				_backLabelPlane.z = 40;
				_backLabelPlane.rotationX = 180;
				_backLabelPlane.visible = false;
			}
		}
		protected function createBackLabelPlane(lbl:String, custom:Boolean = false):void {
			
			if (_backLabelPlane == null) {
				
				_hasCustom = custom;
				
				var bmc:MovieClip = new PlaneBackLabel();
				bmc.definfo = lbl.split("|").join(" ");
				
				var bmat:MovieMaterial = new MovieMaterial(bmc, true, false, false);
				bmc.defmat = bmat;
				bmat.smooth = true;
				bmat.doubleSided = false;
				bmat.interactive = true;
				
				_matref.push(bmat);
				
				_backLabelPlane = new Plane(bmat, bmc.width, bmc.height, 2, 2);
				_backLabelPlane.y = 170;
				_backLabelPlane.x =  _hasCustom ? -260 : -170;
				_backLabelPlane.z = 40;
				_backLabelPlane.rotationX = 180;
				
				_backLabelPlane.visible = false;
			
				_backLabelPlane.addEventListener(InteractiveScene3DEvent.OBJECT_OVER, backRollAction);
				_backLabelPlane.addEventListener(InteractiveScene3DEvent.OBJECT_OUT, backRollAction);
				_backLabelPlane.addEventListener(InteractiveScene3DEvent.OBJECT_CLICK, backClickAction);
				_backContainer.addChild(_backLabelPlane, "backButton");
				_planeRef.push( { face:_backContainer, plane:_backLabelPlane } );
			}
		}
		
		protected function backRollAction(evt:InteractiveScene3DEvent):void {
			_viewport.buttonMode = evt.type == InteractiveScene3DEvent.OBJECT_OVER;
		}
		protected function backClickAction(evt:InteractiveScene3DEvent):void {
			_viewport.buttonMode = false;
			dispatchEvent(new GenericEvent("BackAction"));
		}
		protected function register3DObjectButton(pl:DisplayObject3D):void {
			pl.addEventListener(InteractiveScene3DEvent.OBJECT_OVER, roll3DActions);
			pl.addEventListener(InteractiveScene3DEvent.OBJECT_OUT, roll3DActions);
			pl.addEventListener(InteractiveScene3DEvent.OBJECT_CLICK, click3DActions);
		}
		protected function unregister3DObjectButton(pl:DisplayObject3D):void {
			pl.removeEventListener(InteractiveScene3DEvent.OBJECT_OVER, roll3DActions);
			pl.removeEventListener(InteractiveScene3DEvent.OBJECT_OUT, roll3DActions);
			pl.removeEventListener(InteractiveScene3DEvent.OBJECT_CLICK, click3DActions);
		}
		protected function roll3DActions(evt:InteractiveScene3DEvent):void {
			if (evt.type == InteractiveScene3DEvent.OBJECT_OVER) {
				_audio.playTick();
			}
			_viewport.buttonMode = evt.type == InteractiveScene3DEvent.OBJECT_OVER;
		}
		protected function click3DActions(evt:InteractiveScene3DEvent):void {
			_audio.playEffect(TickClick, { volume:.1 } );
			if((evt.target as Plane).userData){
				var udata:Object = (evt.target as Plane).userData.data;
				
				dispatchEvent(new GenericEvent(GenericEvent.CLICKED, udata.movie.definfo));
			}
			_viewport.buttonMode = false;
		}
		protected function unregisterButton(butt:MovieClip):void {
			_viewport.buttonMode = false;
			butt.removeEventListener(MouseEvent.ROLL_OVER, rollActions);
			butt.removeEventListener(MouseEvent.ROLL_OUT, rollActions);
			butt.removeEventListener(MouseEvent.CLICK, clickActions);
		}
		protected function registerButton(butt:MovieClip):void {
			butt.addEventListener(MouseEvent.ROLL_OVER, rollActions);
			butt.addEventListener(MouseEvent.ROLL_OUT, rollActions);
			butt.addEventListener(MouseEvent.CLICK, clickActions);
		}
		protected function rollActions(evt:MouseEvent):void {
			_viewport.buttonMode = evt.type == MouseEvent.ROLL_OVER;
		}
		protected function clickActions(evt:MouseEvent):void {
			dispatchEvent(new GenericEvent(GenericEvent.CLICKED, evt.target.definfo));
		}
		protected function cleanUpFront():void {
			viewport.buttonMode = false;
			pmenu.deactivate();
			var pplanes:Array = pmenu.planes;
			for each(var pi:PaperMenuItem in pplanes){
				pi.z = 0;
				pi.removeInBetween();
			}
			_frontContainer.visible = false;
			
		}
		protected function cleanUpBack():void {
			viewport.buttonMode = false;
			pmenu.activate();
			_backContainer.visible = false;
		}
		
		public function remove(pobj:DisplayObject3D):void {
			_audio.playFlip();
			TweenMax.killTweensOf(this);
			TweenMax.to(this, .6, { z:-6000, rotationY:rotationY+720, ease:_ease, onComplete:cleanUp, onCompleteParams:[pobj] } );
		}
		public function simpleMoveBack(addz:Number = 100, addy:Number = 60, mult:int = 1):void {
			TweenMax.to(_frontContainer, _speed, { z: -100, ease:_ease } );
			TweenMax.to(_backContainer, _speed, { z: 0, ease:_ease } );
			TweenMax.to(this, _speed, { z:addz*mult, y:addy*mult, ease:_ease } );
			_viewport.buttonMode = false;
		}
		public function simpleMoveForward(remz:Number = 100, remy:Number = 60):void {
			TweenMax.to(this, _speed, { z:z - remz, y:y - remy, ease:_ease } );
			_viewport.buttonMode = false;
		}
		public function returnToZero():void {
			_frontContainer.visible = true;
			TweenMax.to(_frontContainer, _speed, { z: 0, ease:_ease } );
			TweenMax.to(_backContainer, _speed, { z: 0, ease:_ease } );
			setTimeout(hideBackLabel, 500);
			TweenMax.to(this, _speed, { z:0, y:0, rotationY:0, ease:_ease, onComplete:cleanUpBack } );
		}
		public function moveAndFlipBack(addz:Number = 100, addy:Number = 60):void {
			if(rotationY != 180){
				_backContainer.visible = true;
				_backLabelPlane.visible = false;
				TweenMax.to(_frontContainer, _speed, { z: -100, ease:_ease } );
				TweenMax.to(_backContainer, _speed, { z: 0, ease:_ease } );
				setTimeout(showBackLabel, 700);
				TweenMax.to(this, _speed, { z:addz, y:addy, rotationY:180, ease:_ease, onComplete:cleanUpFront } );
				_viewport.buttonMode = false;
			}
		}
		public function moveAndFlipForward(remz:Number = 100, remy:Number = 60):void {
			_frontContainer.visible = true;
			TweenMax.to(_frontContainer, _speed, { z: 0, ease:_ease } );
			TweenMax.to(_backContainer, _speed, { z: remz, ease:_ease } );
			setTimeout(hideBackLabel, 500);
			if(_backed){
				activateControls();
			}
			TweenMax.to(this, _speed, { z:z - remz, y:y - remy, rotationY:rotationY + 180, ease:_ease, onComplete:cleanUpBack } );
		}
		public function activateControls():void {
			var pls:Array = pmenu.planes;
			for each(var pref:PaperMenuItem in pls) {
				register3DObjectButton(pref.basePlaneMaterial);
			}
		}
		public function deactivateControls():void {
			var pls:Array = pmenu.planes;
			for each(var pref:PaperMenuItem in pls) {
				unregister3DObjectButton(pref.basePlaneMaterial);
			}
		}
		public function set renderer(str:String):void {
			_renderer = str;
			renderPlane();
		}
		public function get renderer():String {
			return _renderer;
		}
		public function set viewport(vp:Viewport3D):void {
			_viewport = vp;
		}
		public function get viewport():Viewport3D {
			return _viewport;
		}
		public function set backButtonLabel(str:String):void {
			_backButtonLabel = str;
		}
		public function get backButtonLabel():String {
			return _backButtonLabel;
		}
		public function get contentObject():Object{
			return _defobj;
		}
	}
	
}